<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>编译原理 | Lampow燃的博客</title>
    <meta name="generator" content="VuePress 1.9.9">
    <link rel="icon" href="/blog/assets/img/vincentRan.ico">
    <link rel="manifest" href="/blog/manifest.json">
    <script src="/blog/scripts/global.js"></script>
    <script src="/blog/assets/js/autopush-baidu.js"></script>
    <script src="/blog/assets/js/autopush-360.js"></script>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, minimal-ui">
    <meta name="baidu-site-verification" content="gZcjfbZtAw">
    <meta name="google-site-verification" content="cEMNM1qDYFHDq8a4c2uT9n_3yX6kCJ4KolTcLk9DhV4">
    <meta name="360-site-verification" content="8b6f7e9dff6da70522ce0d5ae8ffd923">
    <meta name="author" content="Lampow燃">
    <meta name="keywords" content="vincentRan;Lampow燃;js;Javascript基础;前端;博客">
    <meta name="theme-color" content="#3eaf7c">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <meta name="msapplication-TileColor" content="#000000">
    
    <link rel="preload" href="/blog/assets/css/0.styles.b6bf8ae6.css" as="style"><link rel="preload" href="/blog/assets/js/app.7b4540b9.js" as="script"><link rel="preload" href="/blog/assets/js/2.b0da3abb.js" as="script"><link rel="preload" href="/blog/assets/js/60.73f12c35.js" as="script"><link rel="preload" href="/blog/assets/js/3.d02dbad1.js" as="script"><link rel="preload" href="/blog/assets/js/11.d9c57454.js" as="script"><link rel="preload" href="/blog/assets/js/6.e0517a23.js" as="script"><link rel="preload" href="/blog/assets/js/4.e142f4c4.js" as="script"><link rel="prefetch" href="/blog/assets/js/10.fad52a34.js"><link rel="prefetch" href="/blog/assets/js/12.67814a82.js"><link rel="prefetch" href="/blog/assets/js/13.dff6097c.js"><link rel="prefetch" href="/blog/assets/js/14.63aca277.js"><link rel="prefetch" href="/blog/assets/js/15.2996c9e2.js"><link rel="prefetch" href="/blog/assets/js/16.97a52145.js"><link rel="prefetch" href="/blog/assets/js/17.cd17994a.js"><link rel="prefetch" href="/blog/assets/js/18.ac420f2a.js"><link rel="prefetch" href="/blog/assets/js/19.eb6b91bf.js"><link rel="prefetch" href="/blog/assets/js/20.cb363eca.js"><link rel="prefetch" href="/blog/assets/js/21.a4e99c33.js"><link rel="prefetch" href="/blog/assets/js/22.694a6ec1.js"><link rel="prefetch" href="/blog/assets/js/23.55cb3c0d.js"><link rel="prefetch" href="/blog/assets/js/24.0f31eaf1.js"><link rel="prefetch" href="/blog/assets/js/25.2eefb2bd.js"><link rel="prefetch" href="/blog/assets/js/26.9375d9cc.js"><link rel="prefetch" href="/blog/assets/js/27.15116a38.js"><link rel="prefetch" href="/blog/assets/js/28.19eef588.js"><link rel="prefetch" href="/blog/assets/js/29.49bf907e.js"><link rel="prefetch" href="/blog/assets/js/30.a3b1e05f.js"><link rel="prefetch" href="/blog/assets/js/31.e816c5a5.js"><link rel="prefetch" href="/blog/assets/js/32.0de6aa66.js"><link rel="prefetch" href="/blog/assets/js/33.0d6966b1.js"><link rel="prefetch" href="/blog/assets/js/34.9b7e8e14.js"><link rel="prefetch" href="/blog/assets/js/35.df38e2a9.js"><link rel="prefetch" href="/blog/assets/js/36.3f437700.js"><link rel="prefetch" href="/blog/assets/js/37.2c1de8b3.js"><link rel="prefetch" href="/blog/assets/js/38.86e11044.js"><link rel="prefetch" href="/blog/assets/js/39.82741cfc.js"><link rel="prefetch" href="/blog/assets/js/40.1e6de0bd.js"><link rel="prefetch" href="/blog/assets/js/41.5b9a2f33.js"><link rel="prefetch" href="/blog/assets/js/42.dbe88c0f.js"><link rel="prefetch" href="/blog/assets/js/43.48e12a76.js"><link rel="prefetch" href="/blog/assets/js/44.c5a6663b.js"><link rel="prefetch" href="/blog/assets/js/45.38f327a2.js"><link rel="prefetch" href="/blog/assets/js/46.527a0e03.js"><link rel="prefetch" href="/blog/assets/js/47.b8baaa72.js"><link rel="prefetch" href="/blog/assets/js/48.3447a56d.js"><link rel="prefetch" href="/blog/assets/js/49.cd301a0f.js"><link rel="prefetch" href="/blog/assets/js/5.d43d130b.js"><link rel="prefetch" href="/blog/assets/js/50.644742a2.js"><link rel="prefetch" href="/blog/assets/js/51.ae6a8437.js"><link rel="prefetch" href="/blog/assets/js/52.dfcb8f83.js"><link rel="prefetch" href="/blog/assets/js/53.2a0715a8.js"><link rel="prefetch" href="/blog/assets/js/54.fe7d4a37.js"><link rel="prefetch" href="/blog/assets/js/55.457aa0d9.js"><link rel="prefetch" href="/blog/assets/js/56.dc026f76.js"><link rel="prefetch" href="/blog/assets/js/57.dfa47cb4.js"><link rel="prefetch" href="/blog/assets/js/58.8dfdbcbb.js"><link rel="prefetch" href="/blog/assets/js/59.67f5108d.js"><link rel="prefetch" href="/blog/assets/js/61.a6281041.js"><link rel="prefetch" href="/blog/assets/js/62.a1672f34.js"><link rel="prefetch" href="/blog/assets/js/63.65b641c6.js"><link rel="prefetch" href="/blog/assets/js/64.01018dd4.js"><link rel="prefetch" href="/blog/assets/js/65.e7ffb165.js"><link rel="prefetch" href="/blog/assets/js/66.173f5f61.js"><link rel="prefetch" href="/blog/assets/js/67.5f7af08d.js"><link rel="prefetch" href="/blog/assets/js/68.d87b9899.js"><link rel="prefetch" href="/blog/assets/js/69.18f0835e.js"><link rel="prefetch" href="/blog/assets/js/7.da19f9b0.js"><link rel="prefetch" href="/blog/assets/js/70.9090fddd.js"><link rel="prefetch" href="/blog/assets/js/71.dd4e6e2c.js"><link rel="prefetch" href="/blog/assets/js/72.c42d4bf3.js"><link rel="prefetch" href="/blog/assets/js/73.5c5defd2.js"><link rel="prefetch" href="/blog/assets/js/74.b12fdeee.js"><link rel="prefetch" href="/blog/assets/js/75.7f085fdb.js"><link rel="prefetch" href="/blog/assets/js/76.f2d01ffb.js"><link rel="prefetch" href="/blog/assets/js/77.23a7ce10.js"><link rel="prefetch" href="/blog/assets/js/78.3b39d101.js"><link rel="prefetch" href="/blog/assets/js/79.42d64efd.js"><link rel="prefetch" href="/blog/assets/js/8.00fa029c.js"><link rel="prefetch" href="/blog/assets/js/80.64996c95.js"><link rel="prefetch" href="/blog/assets/js/81.a15f0118.js"><link rel="prefetch" href="/blog/assets/js/82.726c1156.js"><link rel="prefetch" href="/blog/assets/js/83.8b3a794d.js"><link rel="prefetch" href="/blog/assets/js/84.7cbe7d64.js"><link rel="prefetch" href="/blog/assets/js/85.3ec16acd.js"><link rel="prefetch" href="/blog/assets/js/86.41b3d3af.js"><link rel="prefetch" href="/blog/assets/js/87.c6e2a7c9.js"><link rel="prefetch" href="/blog/assets/js/88.4d4b145b.js"><link rel="prefetch" href="/blog/assets/js/89.04660517.js"><link rel="prefetch" href="/blog/assets/js/9.12b493d7.js"><link rel="prefetch" href="/blog/assets/js/90.9963ca39.js"><link rel="prefetch" href="/blog/assets/js/91.50f67c60.js"><link rel="prefetch" href="/blog/assets/js/92.f109d0d0.js"><link rel="prefetch" href="/blog/assets/js/93.5664c7c2.js"><link rel="prefetch" href="/blog/assets/js/94.889bd5e0.js"><link rel="prefetch" href="/blog/assets/js/95.cfcb0fb3.js">
    <link rel="stylesheet" href="/blog/assets/css/0.styles.b6bf8ae6.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/blog/" class="home-link router-link-active"><img src="/blog/assets/img/vincentRan.jpg" alt="Lampow燃的博客" class="logo"> <span class="site-name can-hide">Lampow燃的博客</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="工作台" class="dropdown-title"><span class="title">工作台</span> <span class="arrow down"></span></button> <button type="button" aria-label="工作台" class="mobile-dropdown-title"><span class="title">工作台</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/blog/article/工作台/工作台.html" class="nav-link">
  工作台
</a></li><li class="dropdown-item"><h4>
          未来探索
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/未来探索/营销公司.html" class="nav-link">
  营销
</a></li><li class="dropdown-subitem"><a href="/blog/article/未来探索/野外单兵防护.html" class="nav-link">
  野外单兵防护
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="计算机原理" class="dropdown-title"><span class="title">计算机原理</span> <span class="arrow down"></span></button> <button type="button" aria-label="计算机原理" class="mobile-dropdown-title"><span class="title">计算机原理</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/blog/article/计算机原理/CPU结构以及简单运行原理.html" class="nav-link">
  CPU结构以及简单运行原理
</a></li><li class="dropdown-item"><!----> <a href="/blog/article/计算机原理/进程和线程.html" class="nav-link">
  进程和线程
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Javascript 基础" class="dropdown-title"><span class="title">Javascript 基础</span> <span class="arrow down"></span></button> <button type="button" aria-label="Javascript 基础" class="mobile-dropdown-title"><span class="title">Javascript 基础</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/blog/article/js-basic/数据类型.html" class="nav-link">
  数据类型
</a></li><li class="dropdown-item"><h4>
          关键字
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/js-basic/关键字/通用关键字.html" class="nav-link">
  通用关键字
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-basic/关键字/async &amp; await.html" class="nav-link">
  async &amp; await
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-basic/关键字/new.html" class="nav-link">
  new
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-basic/关键字/yield.html" class="nav-link">
  yield
</a></li></ul></li><li class="dropdown-item"><h4>
          常用内置对象
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/js-basic/内置对象/Object.html" class="nav-link">
  Object
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-basic/内置对象/Function.html" class="nav-link">
  Function
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-basic/内置对象/GeneratorFunction.html" class="nav-link">
  GeneratorFunction
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-basic/内置对象/Promise.html" class="nav-link">
  Promise
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-basic/内置对象/Reflect.html" class="nav-link">
  Reflect
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-basic/内置对象/Array.html" class="nav-link">
  Array
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-basic/内置对象/Set.html" class="nav-link">
  Set
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-basic/内置对象/Proxy.html" class="nav-link">
  Proxy
</a></li></ul></li><li class="dropdown-item"><h4>
          构造函数-原型-原型链
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/js-basic/构造函数-原型-原型链/构造函数.html" class="nav-link">
  构造函数
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-basic/构造函数-原型-原型链/原型.html" class="nav-link">
  原型
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-basic/构造函数-原型-原型链/原型链.html" class="nav-link">
  原型链
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-basic/构造函数-原型-原型链/箭头函数.html" class="nav-link">
  箭头函数
</a></li></ul></li><li class="dropdown-item"><!----> <a href="/blog/article/js-basic/1-4、数组操作.html" class="nav-link">
  数组操作
</a></li><li class="dropdown-item"><!----> <a href="/blog/article/js-basic/深浅拷贝.html" class="nav-link">
  引用类型之深拷贝浅拷贝
</a></li><li class="dropdown-item"><!----> <a href="/blog/article/js-basic/1-6、知识体系.html" class="nav-link">
  知识体系
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Javascript 进阶" class="dropdown-title"><span class="title">Javascript 进阶</span> <span class="arrow down"></span></button> <button type="button" aria-label="Javascript 进阶" class="mobile-dropdown-title"><span class="title">Javascript 进阶</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/blog/article/js-upgrade/模块化/模块化.html" class="nav-link">
  模块化
</a></li><li class="dropdown-item"><h4>
          性能优化
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/js-upgrade/性能优化/避免内存泄漏.html" class="nav-link">
  避免内存泄漏
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-upgrade/性能优化/v8垃圾回收机制.html" class="nav-link">
  v8垃圾回收机制
</a></li></ul></li><li class="dropdown-item"><h4>
          编程范式
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/js-upgrade/编程范式/编程范式.html" class="nav-link">
  编程范式
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-upgrade/编程范式/面向对象_封装.html" class="nav-link">
  面向对象编程
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-upgrade/编程范式/函数式编程.html" class="nav-link">
  函数式编程
</a></li></ul></li><li class="dropdown-item"><h4>
          编程原则
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/js-upgrade/编程原则/编程原则.html" class="nav-link">
  编程原则
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-upgrade/编程原则/Immutable原则.html" class="nav-link">
  Immutable原则
</a></li></ul></li><li class="dropdown-item"><h4>
          设计模式
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/js-upgrade/设计模式/什么是设计模式.html" class="nav-link">
  什么是设计模式
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-upgrade/设计模式/访问者模式.html" class="nav-link">
  访问者模式
</a></li></ul></li><li class="dropdown-item"><h4>
          常见算法
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/js-upgrade/算法/贪心算法.html" class="nav-link">
  贪心算法
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-upgrade/算法/LRU（least recently used）.html" class="nav-link">
  LRU（least recently used）
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="框架" class="dropdown-title"><span class="title">框架</span> <span class="arrow down"></span></button> <button type="button" aria-label="框架" class="mobile-dropdown-title"><span class="title">框架</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          NestJS
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/框架/NestJS/初始NestJS.html" class="nav-link">
  初始NestJS
</a></li><li class="dropdown-subitem"><a href="/blog/article/框架/NestJS/数据库.html" class="nav-link">
  数据库
</a></li></ul></li><li class="dropdown-item"><h4>
          typescript
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/框架/typescript/初识TypeScript.html" class="nav-link">
  初识TypeScript
</a></li><li class="dropdown-subitem"><a href="/blog/article/框架/typescript/基本类型.html" class="nav-link">
  基本类型
</a></li><li class="dropdown-subitem"><a href="/blog/article/框架/typescript/进阶类型.html" class="nav-link">
  进阶类型
</a></li><li class="dropdown-subitem"><a href="/blog/article/框架/typescript/最佳实践.html" class="nav-link">
  最佳实践
</a></li></ul></li><li class="dropdown-item"><h4>
          React
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/框架/react/基础用法.html" class="nav-link">
  基础用法
</a></li></ul></li><li class="dropdown-item"><h4>
          Vue
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/框架/vue/生命周期&amp;执行过程.html" class="nav-link">
  生命周期&amp;执行过程
</a></li><li class="dropdown-subitem"><a href="/blog/article/框架/vue/组件间通信.html" class="nav-link">
  组件间通信
</a></li><li class="dropdown-subitem"><a href="/blog/article/框架/vue/自定义指令.html" class="nav-link">
  自定义指令
</a></li><li class="dropdown-subitem"><a href="/blog/article/框架/vue/手撸ViewModel.html" class="nav-link">
  手撸ViewModel
</a></li><li class="dropdown-subitem"><a href="/blog/article/框架/vue/源码解析/核心源码模块.html" class="nav-link">
  源码解析
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="前端工程化" class="dropdown-title"><span class="title">前端工程化</span> <span class="arrow down"></span></button> <button type="button" aria-label="前端工程化" class="mobile-dropdown-title"><span class="title">前端工程化</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          持续集成与交付
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/前端工程化/CI&amp;CD/CI&amp;CD.html" class="nav-link">
  持续集成与交付
</a></li><li class="dropdown-subitem"><a href="/blog/article/前端工程化/CI&amp;CD/编译打包/编译原理.html" class="nav-link">
  编译打包
</a></li><li class="dropdown-subitem"><a href="/blog/article/前端工程化/CI&amp;CD/自动化测试/自动化测试.html" class="nav-link">
  自动化测试
</a></li></ul></li><li class="dropdown-item"><h4>
          脚手架开发
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/前端工程化/脚手架开发/npm原生/npm脚手架开发.html" class="nav-link">
  npm原生
</a></li><li class="dropdown-subitem"><a href="/blog/article/前端工程化/脚手架开发/lerna库/快速上手.html" class="nav-link">
  lerna库
</a></li><li class="dropdown-subitem"><a href="/blog/article/前端工程化/脚手架开发/commander/commander.html" class="nav-link">
  commander管理命令
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="工具代码" class="dropdown-title"><span class="title">工具代码</span> <span class="arrow down"></span></button> <button type="button" aria-label="工具代码" class="mobile-dropdown-title"><span class="title">工具代码</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/blog/article/工具代码/正则.html" class="nav-link">
  正则
</a></li><li class="dropdown-item"><!----> <a href="/blog/article/工具代码/浏览器扩展.html" class="nav-link">
  浏览器扩展
</a></li><li class="dropdown-item"><h4>
          轮子系列
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/工具代码/轮子系列/订阅发布模式.html" class="nav-link">
  订阅发布模式
</a></li><li class="dropdown-subitem"><a href="/blog/article/工具代码/轮子系列/深拷贝.html" class="nav-link">
  深拷贝
</a></li><li class="dropdown-subitem"><a href="/blog/article/工具代码/轮子系列/Promise.html" class="nav-link">
  22行简洁的Promise
</a></li><li class="dropdown-subitem"><a href="/blog/article/工具代码/轮子系列/健壮的Promise.html" class="nav-link">
  健壮的Promise
</a></li><li class="dropdown-subitem"><a href="/blog/article/工具代码/轮子系列/节流and防抖.html" class="nav-link">
  节流and防抖
</a></li><li class="dropdown-subitem"><a href="/blog/article/工具代码/轮子系列/链表.html" class="nav-link">
  链表
</a></li><li class="dropdown-subitem"><a href="/blog/article/工具代码/轮子系列/Immer核心.html" class="nav-link">
  Immer核心
</a></li><li class="dropdown-subitem"><a href="/blog/article/工具代码/轮子系列/手写new.html" class="nav-link">
  手写new
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="web3D" class="dropdown-title"><span class="title">web3D</span> <span class="arrow down"></span></button> <button type="button" aria-label="web3D" class="mobile-dropdown-title"><span class="title">web3D</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/blog/article/web3D/webgl/plan.html" class="nav-link">
  学习计划
</a></li><li class="dropdown-item"><!----> <a href="/blog/article/web3D/webgl/WebGL2_Attr.html" class="nav-link">
  WebGL2 属性
</a></li><li class="dropdown-item"><!----> <a href="/blog/article/web3D/webgl/WebGL2_API.html" class="nav-link">
  WebGL2 API
</a></li><li class="dropdown-item"><!----> <a href="/blog/article/web3D/webgl/WebGL2_Interface.html" class="nav-link">
  WebGL2 接口
</a></li></ul></div></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="工作台" class="dropdown-title"><span class="title">工作台</span> <span class="arrow down"></span></button> <button type="button" aria-label="工作台" class="mobile-dropdown-title"><span class="title">工作台</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/blog/article/工作台/工作台.html" class="nav-link">
  工作台
</a></li><li class="dropdown-item"><h4>
          未来探索
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/未来探索/营销公司.html" class="nav-link">
  营销
</a></li><li class="dropdown-subitem"><a href="/blog/article/未来探索/野外单兵防护.html" class="nav-link">
  野外单兵防护
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="计算机原理" class="dropdown-title"><span class="title">计算机原理</span> <span class="arrow down"></span></button> <button type="button" aria-label="计算机原理" class="mobile-dropdown-title"><span class="title">计算机原理</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/blog/article/计算机原理/CPU结构以及简单运行原理.html" class="nav-link">
  CPU结构以及简单运行原理
</a></li><li class="dropdown-item"><!----> <a href="/blog/article/计算机原理/进程和线程.html" class="nav-link">
  进程和线程
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Javascript 基础" class="dropdown-title"><span class="title">Javascript 基础</span> <span class="arrow down"></span></button> <button type="button" aria-label="Javascript 基础" class="mobile-dropdown-title"><span class="title">Javascript 基础</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/blog/article/js-basic/数据类型.html" class="nav-link">
  数据类型
</a></li><li class="dropdown-item"><h4>
          关键字
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/js-basic/关键字/通用关键字.html" class="nav-link">
  通用关键字
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-basic/关键字/async &amp; await.html" class="nav-link">
  async &amp; await
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-basic/关键字/new.html" class="nav-link">
  new
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-basic/关键字/yield.html" class="nav-link">
  yield
</a></li></ul></li><li class="dropdown-item"><h4>
          常用内置对象
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/js-basic/内置对象/Object.html" class="nav-link">
  Object
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-basic/内置对象/Function.html" class="nav-link">
  Function
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-basic/内置对象/GeneratorFunction.html" class="nav-link">
  GeneratorFunction
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-basic/内置对象/Promise.html" class="nav-link">
  Promise
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-basic/内置对象/Reflect.html" class="nav-link">
  Reflect
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-basic/内置对象/Array.html" class="nav-link">
  Array
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-basic/内置对象/Set.html" class="nav-link">
  Set
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-basic/内置对象/Proxy.html" class="nav-link">
  Proxy
</a></li></ul></li><li class="dropdown-item"><h4>
          构造函数-原型-原型链
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/js-basic/构造函数-原型-原型链/构造函数.html" class="nav-link">
  构造函数
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-basic/构造函数-原型-原型链/原型.html" class="nav-link">
  原型
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-basic/构造函数-原型-原型链/原型链.html" class="nav-link">
  原型链
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-basic/构造函数-原型-原型链/箭头函数.html" class="nav-link">
  箭头函数
</a></li></ul></li><li class="dropdown-item"><!----> <a href="/blog/article/js-basic/1-4、数组操作.html" class="nav-link">
  数组操作
</a></li><li class="dropdown-item"><!----> <a href="/blog/article/js-basic/深浅拷贝.html" class="nav-link">
  引用类型之深拷贝浅拷贝
</a></li><li class="dropdown-item"><!----> <a href="/blog/article/js-basic/1-6、知识体系.html" class="nav-link">
  知识体系
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Javascript 进阶" class="dropdown-title"><span class="title">Javascript 进阶</span> <span class="arrow down"></span></button> <button type="button" aria-label="Javascript 进阶" class="mobile-dropdown-title"><span class="title">Javascript 进阶</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/blog/article/js-upgrade/模块化/模块化.html" class="nav-link">
  模块化
</a></li><li class="dropdown-item"><h4>
          性能优化
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/js-upgrade/性能优化/避免内存泄漏.html" class="nav-link">
  避免内存泄漏
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-upgrade/性能优化/v8垃圾回收机制.html" class="nav-link">
  v8垃圾回收机制
</a></li></ul></li><li class="dropdown-item"><h4>
          编程范式
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/js-upgrade/编程范式/编程范式.html" class="nav-link">
  编程范式
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-upgrade/编程范式/面向对象_封装.html" class="nav-link">
  面向对象编程
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-upgrade/编程范式/函数式编程.html" class="nav-link">
  函数式编程
</a></li></ul></li><li class="dropdown-item"><h4>
          编程原则
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/js-upgrade/编程原则/编程原则.html" class="nav-link">
  编程原则
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-upgrade/编程原则/Immutable原则.html" class="nav-link">
  Immutable原则
</a></li></ul></li><li class="dropdown-item"><h4>
          设计模式
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/js-upgrade/设计模式/什么是设计模式.html" class="nav-link">
  什么是设计模式
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-upgrade/设计模式/访问者模式.html" class="nav-link">
  访问者模式
</a></li></ul></li><li class="dropdown-item"><h4>
          常见算法
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/js-upgrade/算法/贪心算法.html" class="nav-link">
  贪心算法
</a></li><li class="dropdown-subitem"><a href="/blog/article/js-upgrade/算法/LRU（least recently used）.html" class="nav-link">
  LRU（least recently used）
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="框架" class="dropdown-title"><span class="title">框架</span> <span class="arrow down"></span></button> <button type="button" aria-label="框架" class="mobile-dropdown-title"><span class="title">框架</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          NestJS
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/框架/NestJS/初始NestJS.html" class="nav-link">
  初始NestJS
</a></li><li class="dropdown-subitem"><a href="/blog/article/框架/NestJS/数据库.html" class="nav-link">
  数据库
</a></li></ul></li><li class="dropdown-item"><h4>
          typescript
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/框架/typescript/初识TypeScript.html" class="nav-link">
  初识TypeScript
</a></li><li class="dropdown-subitem"><a href="/blog/article/框架/typescript/基本类型.html" class="nav-link">
  基本类型
</a></li><li class="dropdown-subitem"><a href="/blog/article/框架/typescript/进阶类型.html" class="nav-link">
  进阶类型
</a></li><li class="dropdown-subitem"><a href="/blog/article/框架/typescript/最佳实践.html" class="nav-link">
  最佳实践
</a></li></ul></li><li class="dropdown-item"><h4>
          React
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/框架/react/基础用法.html" class="nav-link">
  基础用法
</a></li></ul></li><li class="dropdown-item"><h4>
          Vue
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/框架/vue/生命周期&amp;执行过程.html" class="nav-link">
  生命周期&amp;执行过程
</a></li><li class="dropdown-subitem"><a href="/blog/article/框架/vue/组件间通信.html" class="nav-link">
  组件间通信
</a></li><li class="dropdown-subitem"><a href="/blog/article/框架/vue/自定义指令.html" class="nav-link">
  自定义指令
</a></li><li class="dropdown-subitem"><a href="/blog/article/框架/vue/手撸ViewModel.html" class="nav-link">
  手撸ViewModel
</a></li><li class="dropdown-subitem"><a href="/blog/article/框架/vue/源码解析/核心源码模块.html" class="nav-link">
  源码解析
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="前端工程化" class="dropdown-title"><span class="title">前端工程化</span> <span class="arrow down"></span></button> <button type="button" aria-label="前端工程化" class="mobile-dropdown-title"><span class="title">前端工程化</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          持续集成与交付
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/前端工程化/CI&amp;CD/CI&amp;CD.html" class="nav-link">
  持续集成与交付
</a></li><li class="dropdown-subitem"><a href="/blog/article/前端工程化/CI&amp;CD/编译打包/编译原理.html" class="nav-link">
  编译打包
</a></li><li class="dropdown-subitem"><a href="/blog/article/前端工程化/CI&amp;CD/自动化测试/自动化测试.html" class="nav-link">
  自动化测试
</a></li></ul></li><li class="dropdown-item"><h4>
          脚手架开发
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/前端工程化/脚手架开发/npm原生/npm脚手架开发.html" class="nav-link">
  npm原生
</a></li><li class="dropdown-subitem"><a href="/blog/article/前端工程化/脚手架开发/lerna库/快速上手.html" class="nav-link">
  lerna库
</a></li><li class="dropdown-subitem"><a href="/blog/article/前端工程化/脚手架开发/commander/commander.html" class="nav-link">
  commander管理命令
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="工具代码" class="dropdown-title"><span class="title">工具代码</span> <span class="arrow down"></span></button> <button type="button" aria-label="工具代码" class="mobile-dropdown-title"><span class="title">工具代码</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/blog/article/工具代码/正则.html" class="nav-link">
  正则
</a></li><li class="dropdown-item"><!----> <a href="/blog/article/工具代码/浏览器扩展.html" class="nav-link">
  浏览器扩展
</a></li><li class="dropdown-item"><h4>
          轮子系列
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blog/article/工具代码/轮子系列/订阅发布模式.html" class="nav-link">
  订阅发布模式
</a></li><li class="dropdown-subitem"><a href="/blog/article/工具代码/轮子系列/深拷贝.html" class="nav-link">
  深拷贝
</a></li><li class="dropdown-subitem"><a href="/blog/article/工具代码/轮子系列/Promise.html" class="nav-link">
  22行简洁的Promise
</a></li><li class="dropdown-subitem"><a href="/blog/article/工具代码/轮子系列/健壮的Promise.html" class="nav-link">
  健壮的Promise
</a></li><li class="dropdown-subitem"><a href="/blog/article/工具代码/轮子系列/节流and防抖.html" class="nav-link">
  节流and防抖
</a></li><li class="dropdown-subitem"><a href="/blog/article/工具代码/轮子系列/链表.html" class="nav-link">
  链表
</a></li><li class="dropdown-subitem"><a href="/blog/article/工具代码/轮子系列/Immer核心.html" class="nav-link">
  Immer核心
</a></li><li class="dropdown-subitem"><a href="/blog/article/工具代码/轮子系列/手写new.html" class="nav-link">
  手写new
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="web3D" class="dropdown-title"><span class="title">web3D</span> <span class="arrow down"></span></button> <button type="button" aria-label="web3D" class="mobile-dropdown-title"><span class="title">web3D</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/blog/article/web3D/webgl/plan.html" class="nav-link">
  学习计划
</a></li><li class="dropdown-item"><!----> <a href="/blog/article/web3D/webgl/WebGL2_Attr.html" class="nav-link">
  WebGL2 属性
</a></li><li class="dropdown-item"><!----> <a href="/blog/article/web3D/webgl/WebGL2_API.html" class="nav-link">
  WebGL2 API
</a></li><li class="dropdown-item"><!----> <a href="/blog/article/web3D/webgl/WebGL2_Interface.html" class="nav-link">
  WebGL2 接口
</a></li></ul></div></div> <!----></nav>  <ul class="sidebar-links"><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>工作台</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>计算机原理</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>Javascript 基础</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>Javascript 进阶</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>框架</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading open"><span>前端工程化</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><section class="sidebar-group collapsable is-sub-group depth-1"><a href="/blog/article/前端工程化/CI&amp;CD/CI&amp;CD" class="sidebar-heading clickable open"><span>持续集成与交付</span> <span class="arrow down"></span></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/blog/article/前端工程化/CI&amp;CD/CI&amp;CD.html" class="sidebar-link">持续集成与交付</a></li><li><section class="sidebar-group collapsable is-sub-group depth-2"><a href="/blog/article/前端工程化/CI&amp;CD/编译打包/编译原理" class="sidebar-heading clickable open active"><span>编译打包</span> <span class="arrow down"></span></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/blog/article/前端工程化/CI&amp;CD/编译打包/编译原理.html" class="active sidebar-link">编译原理</a></li><li><section class="sidebar-group collapsable is-sub-group depth-3"><a href="/blog/article/前端工程化/CI&amp;CD/编译打包/编译工具" class="sidebar-heading clickable"><span>编译工具</span> <span class="arrow right"></span></a> <!----></section></li><li><a href="/blog/article/前端工程化/CI&amp;CD/编译打包/包管理工具.html" class="sidebar-link">包管理工具</a></li></ul></section></li><li><a href="/blog/article/前端工程化/CI&amp;CD/自动化测试/自动化测试.html" class="sidebar-link">自动化测试</a></li></ul></section></li><li><section class="sidebar-group collapsable is-sub-group depth-1"><a href="/blog/article/前端工程化/脚手架开发/npm原生/npm脚手架开发" class="sidebar-heading clickable"><span>脚手架开发</span> <span class="arrow right"></span></a> <!----></section></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>工具代码</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>web3D</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h2 id="编译原理"><a href="#编译原理" class="header-anchor">#</a> 编译原理</h2> <div class="custom-block tip"><p class="custom-block-title">编译原理</p> <p>编译原理是计算机科学中的一个重要分支，主要研究<code>编程语言</code>的<code>编译过程</code>以及<code>编译器</code>的设计与实现。<code>编译器</code>是将<code>A程序语言</code>（源代码）转换为<code>B程序语言</code>（目标代码）的专用程序</p></div> <div class="custom-block tip"><p class="custom-block-title">AST 抽象语法树</p> <h4 id="ast-是一种在编程语言处理中常用的数据结构-用于表示源代码的抽象语法结构。它并不是一个统一规定的数据结构-而是根据不同的编程语言和工具-以及处理的需求-可能会有不同的实现和表示方式。"><a href="#ast-是一种在编程语言处理中常用的数据结构-用于表示源代码的抽象语法结构。它并不是一个统一规定的数据结构-而是根据不同的编程语言和工具-以及处理的需求-可能会有不同的实现和表示方式。" class="header-anchor">#</a> <code>AST</code> 是一种在编程语言处理中常用的<code>数据结构</code>，用于表示源代码的抽象语法结构。它<code>并不是一个统一规定的数据结构</code>，而是根据不同的编程语言和工具，以及处理的需求，<code>可能会有不同的实现和表示方式</code>。</h4> <h4 id="ast-在编译器、解析器、静态分析工具、代码转换工具等领域被广泛使用-它可以帮助程序理解、分析和处理源代码。ast-通常由节点-node-组成-每个节点代表源代码中的一个语法结构-如变量、函数、表达式、语句等。"><a href="#ast-在编译器、解析器、静态分析工具、代码转换工具等领域被广泛使用-它可以帮助程序理解、分析和处理源代码。ast-通常由节点-node-组成-每个节点代表源代码中的一个语法结构-如变量、函数、表达式、语句等。" class="header-anchor">#</a> AST 在<code>编译器</code>、<code>解析器</code>、<code>静态分析工具</code>、<code>代码转换工具</code>等领域被广泛使用，它可以帮助程序理解、分析和处理源代码。AST 通常由<code>节点（Node）</code>组成，每个节点代表源代码中的一个<code>语法结构</code>，如<code>变量</code>、<code>函数</code>、<code>表达式</code>、<code>语句</code>等。</h4> <h4 id="常用-ast-编译器执行步骤-语法分析-词法分析-中间-ast-目标-ast-目标code"><a href="#常用-ast-编译器执行步骤-语法分析-词法分析-中间-ast-目标-ast-目标code" class="header-anchor">#</a> 常用 AST 编译器执行步骤：<code>语法分析</code>-&gt; <code>词法分析</code> -&gt; <code>中间 AST</code> -&gt; <code>目标 AST</code> -&gt; <code>目标code</code></h4></div> <h2 id="一般编译器执行步骤"><a href="#一般编译器执行步骤" class="header-anchor">#</a> 一般编译器执行步骤：</h2> <ol><li><code>词法分析</code>（Lexical Analysis）：将源代码分解为<code>词法单元</code>（Token），例如<code>关键字、标识符、运算符</code>等。</li> <li><code>语法分析</code>（Syntax Analysis）：将词法单元转换成<code>AST树</code>，检查程序是否符合语法规则。</li> <li><code>代码转换</code>（Intermediate Code Generation）：将<code>源代码</code>转换成一种<code>中间表示形式</code>，方便后续优化和目标代码生成。</li> <li><code>代码生成</code>（Code Generation）：将<code>中间代码</code>转换为<code>目标机器代码</code>，与特定硬件架构相适应。</li></ol> <div class="custom-block warning"><p class="custom-block-title">注意</p> <h4 id="编译原理更多地像一个设计模式-指导如何去将一种代码转换成另一种代码的常用思路"><a href="#编译原理更多地像一个设计模式-指导如何去将一种代码转换成另一种代码的常用思路" class="header-anchor">#</a> 编译原理更多地像一个设计模式，指导如何去将一种代码转换成另一种代码的常用思路</h4> <h4 id="精辟-编译器就是经过一系列字符串的操作-将一种字符串-转换成另一种字符串"><a href="#精辟-编译器就是经过一系列字符串的操作-将一种字符串-转换成另一种字符串" class="header-anchor">#</a> 精辟：<code>编译器就是经过一系列字符串的操作，将一种字符串，转换成另一种字符串</code></h4></div> <h2 id="简易编译器"><a href="#简易编译器" class="header-anchor">#</a> 简易编译器</h2> <div class="custom-block tip"><p class="custom-block-title">核心步骤</p> <p><code>语法分析</code>-&gt; <code>词法分析</code> -&gt; <code>中间 AST</code> -&gt; <code>目标 AST</code> -&gt; <code>目标code</code></p></div> <div class="custom-block tip"><p class="custom-block-title">核心设计模式 访问者(visitor)模式</p> <p>在代码转换生成目标 ast 的时候，基本都使用 <a href="/blog/article/js-upgrade/设计模式/访问者模式.html">visitor 模式</a>管理转换逻辑</p></div> <div style="display:flex;flex-direction:column;align-items:center;"><div style="width: 100%; display: flex; align-items: center; justify-content: space-between"><div class="code-wrapper origin"><p>开发代码</p> <textarea rows="10" class="editor-input"></textarea></div> <button class="handle-btn">转换</button> <div class="code-wrapper target"><p>编译后代码</p> <textarea rows="10" disabled="disabled" class="editor-input"></textarea></div></div></div> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">//           LISP                     C</span>
<span class="token comment">// 2+(4-2)   (add 2 (subtract 4 2))   add(2, subtract(4, 2))</span>

<span class="token comment">// 词法分析 -&gt; tokens</span>
<span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function-variable function">tokenizer</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">input</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">let</span> current <span class="token operator">=</span> <span class="token number">0</span>
  <span class="token keyword">let</span> tokens <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
  <span class="token keyword">const</span> parens <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">'('</span><span class="token punctuation">,</span> <span class="token string">')'</span><span class="token punctuation">]</span>
  <span class="token keyword">const</span> handles <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">'+'</span><span class="token punctuation">,</span> <span class="token string">'-'</span><span class="token punctuation">,</span> <span class="token string">'*'</span><span class="token punctuation">,</span> <span class="token string">'/'</span><span class="token punctuation">,</span> <span class="token string">'='</span><span class="token punctuation">]</span>

  <span class="token keyword">while</span> <span class="token punctuation">(</span>current <span class="token operator">&lt;</span> input<span class="token punctuation">.</span>length<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">let</span> char <span class="token operator">=</span> input<span class="token punctuation">[</span>current<span class="token punctuation">]</span>

    <span class="token comment">// 特殊字符</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>parens<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span>char<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      tokens<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
        <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'paren'</span><span class="token punctuation">,</span>
        <span class="token literal-property property">value</span><span class="token operator">:</span> char<span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span>

      current<span class="token operator">++</span>
      <span class="token keyword">continue</span>
    <span class="token punctuation">}</span>

    <span class="token comment">// 操作符</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>handles<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span>char<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      tokens<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
        <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'handle'</span><span class="token punctuation">,</span>
        <span class="token literal-property property">value</span><span class="token operator">:</span> char<span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span>

      current<span class="token operator">++</span>
      <span class="token keyword">continue</span>
    <span class="token punctuation">}</span>

    <span class="token comment">// 过滤空格</span>
    <span class="token keyword">let</span> <span class="token constant">WHITESPACE</span> <span class="token operator">=</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\s</span><span class="token regex-delimiter">/</span></span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token constant">WHITESPACE</span><span class="token punctuation">.</span><span class="token function">test</span><span class="token punctuation">(</span>char<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      current<span class="token operator">++</span>
      <span class="token keyword">continue</span>
    <span class="token punctuation">}</span>

    <span class="token comment">// 数字</span>
    <span class="token keyword">let</span> <span class="token constant">NUMBERS</span> <span class="token operator">=</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">[0-9]</span><span class="token regex-delimiter">/</span></span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token constant">NUMBERS</span><span class="token punctuation">.</span><span class="token function">test</span><span class="token punctuation">(</span>char<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">let</span> value <span class="token operator">=</span> <span class="token string">''</span>
      <span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token constant">NUMBERS</span><span class="token punctuation">.</span><span class="token function">test</span><span class="token punctuation">(</span>char<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        value <span class="token operator">+=</span> char
        char <span class="token operator">=</span> input<span class="token punctuation">[</span><span class="token operator">++</span>current<span class="token punctuation">]</span>
      <span class="token punctuation">}</span>
      tokens<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
        <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'number'</span><span class="token punctuation">,</span>
        value<span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span>

      <span class="token keyword">continue</span>
    <span class="token punctuation">}</span>

    <span class="token comment">// 字符串</span>
    <span class="token keyword">let</span> <span class="token function-variable function">ASERT_STRINGS</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">str</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> str <span class="token operator">===</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">&quot;</span><span class="token template-punctuation string">`</span></span> <span class="token operator">||</span> str <span class="token operator">===</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">'</span><span class="token template-punctuation string">`</span></span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token constant">ASERT_STRINGS</span><span class="token punctuation">(</span>char<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">let</span> value <span class="token operator">=</span> <span class="token string">''</span>
      char <span class="token operator">=</span> input<span class="token punctuation">[</span><span class="token operator">++</span>current<span class="token punctuation">]</span>
      <span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token constant">ASERT_STRINGS</span><span class="token punctuation">(</span>char<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        value <span class="token operator">+=</span> char
        char <span class="token operator">=</span> input<span class="token punctuation">[</span><span class="token operator">++</span>current<span class="token punctuation">]</span>
      <span class="token punctuation">}</span>
      tokens<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
        <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'string'</span><span class="token punctuation">,</span>
        value<span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span>
      <span class="token comment">// 过滤结尾的引号</span>
      current<span class="token operator">++</span>
      <span class="token keyword">continue</span>
    <span class="token punctuation">}</span>

    <span class="token comment">// 关键字</span>
    <span class="token keyword">let</span> <span class="token constant">LETTERS</span> <span class="token operator">=</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">[a-z]</span><span class="token regex-delimiter">/</span><span class="token regex-flags">i</span></span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token constant">LETTERS</span><span class="token punctuation">.</span><span class="token function">test</span><span class="token punctuation">(</span>char<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">let</span> value <span class="token operator">=</span> <span class="token string">''</span>
      <span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token constant">LETTERS</span><span class="token punctuation">.</span><span class="token function">test</span><span class="token punctuation">(</span>char<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        value <span class="token operator">+=</span> char
        char <span class="token operator">=</span> input<span class="token punctuation">[</span><span class="token operator">++</span>current<span class="token punctuation">]</span>
      <span class="token punctuation">}</span>
      tokens<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
        <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'name'</span><span class="token punctuation">,</span>
        value<span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span>
      <span class="token keyword">continue</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">TypeError</span><span class="token punctuation">(</span><span class="token string">'没有其他类型处理指定元素'</span><span class="token punctuation">,</span> char<span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  <span class="token keyword">return</span> tokens
<span class="token punctuation">}</span>

<span class="token comment">// 语法分析 -&gt; 原始 AST</span>
<span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function-variable function">parser</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">tokens</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">let</span> current <span class="token operator">=</span> <span class="token number">0</span>

  <span class="token comment">// 步进器，生成ast树的核心方法</span>
  <span class="token keyword">const</span> <span class="token function-variable function">walk</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">let</span> token <span class="token operator">=</span> tokens<span class="token punctuation">[</span>current<span class="token punctuation">]</span>

    <span class="token comment">// 数值</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>token<span class="token punctuation">.</span>type <span class="token operator">===</span> <span class="token string">'number'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      current<span class="token operator">++</span>
      <span class="token keyword">return</span> <span class="token punctuation">{</span>
        <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'NumberLiteral'</span><span class="token punctuation">,</span> <span class="token comment">// Literal 字面量</span>
        <span class="token literal-property property">value</span><span class="token operator">:</span> token<span class="token punctuation">.</span>value<span class="token punctuation">,</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    <span class="token comment">// 字符串</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>token<span class="token punctuation">.</span>type <span class="token operator">===</span> <span class="token string">'string'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      current<span class="token operator">++</span>
      <span class="token keyword">return</span> <span class="token punctuation">{</span>
        <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'StringLiteral'</span><span class="token punctuation">,</span> <span class="token comment">// Literal 字面量</span>
        <span class="token literal-property property">value</span><span class="token operator">:</span> token<span class="token punctuation">.</span>value<span class="token punctuation">,</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    <span class="token comment">// 操作符</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>token<span class="token punctuation">.</span>type <span class="token operator">===</span> <span class="token string">'handle'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      current<span class="token operator">++</span>
      <span class="token keyword">return</span> <span class="token punctuation">{</span>
        <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'HandleLiteral'</span><span class="token punctuation">,</span> <span class="token comment">// Literal 字面量</span>
        <span class="token literal-property property">value</span><span class="token operator">:</span> token<span class="token punctuation">.</span>value<span class="token punctuation">,</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    <span class="token comment">// 表达式提取（此处默认(后续就是表达式）</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>token<span class="token punctuation">.</span>type <span class="token operator">===</span> <span class="token string">'paren'</span> <span class="token operator">&amp;&amp;</span> token<span class="token punctuation">.</span>value <span class="token operator">===</span> <span class="token string">'('</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      token <span class="token operator">=</span> tokens<span class="token punctuation">[</span><span class="token operator">++</span>current<span class="token punctuation">]</span> <span class="token comment">// next token</span>
      <span class="token keyword">let</span> node <span class="token operator">=</span> <span class="token punctuation">{</span>
        <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'CallExpression'</span><span class="token punctuation">,</span>
        <span class="token literal-property property">name</span><span class="token operator">:</span> token<span class="token punctuation">.</span>value<span class="token punctuation">,</span>
        <span class="token literal-property property">params</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
      <span class="token punctuation">}</span>
      token <span class="token operator">=</span> tokens<span class="token punctuation">[</span><span class="token operator">++</span>current<span class="token punctuation">]</span> <span class="token comment">// next token</span>
      <span class="token comment">// 收集括号间的表达式</span>
      <span class="token keyword">while</span> <span class="token punctuation">(</span>token<span class="token punctuation">.</span>value <span class="token operator">!==</span> <span class="token string">')'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        node<span class="token punctuation">.</span>params<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token function">walk</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// 收集表达式</span>
        token <span class="token operator">=</span> tokens<span class="token punctuation">[</span>current<span class="token punctuation">]</span> <span class="token comment">// 执行一次walk后current会被++，此token会往后递增</span>
      <span class="token punctuation">}</span>

      <span class="token comment">// 收集完，将结束括号跳过</span>
      current<span class="token operator">++</span>
      <span class="token keyword">return</span> node
    <span class="token punctuation">}</span>

    <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">TypeError</span><span class="token punctuation">(</span>token<span class="token punctuation">.</span>type<span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  <span class="token keyword">let</span> ast <span class="token operator">=</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'Program'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">body</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span>

  <span class="token keyword">while</span> <span class="token punctuation">(</span>current <span class="token operator">&lt;</span> tokens<span class="token punctuation">.</span>length<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    ast<span class="token punctuation">.</span>body<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token function">walk</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">return</span> ast
<span class="token punctuation">}</span>

<span class="token comment">// 目标 AST</span>
<span class="token comment">// {</span>
<span class="token comment">//   type: 'Program',</span>
<span class="token comment">//   body: [</span>
<span class="token comment">//     {</span>
<span class="token comment">//       type: 'ExpressionStatement',</span>
<span class="token comment">//       expression: {</span>
<span class="token comment">//         type: 'CallExpression',</span>
<span class="token comment">//         callee: {</span>
<span class="token comment">//           type: 'Identifier',</span>
<span class="token comment">//           name: 'add',</span>
<span class="token comment">//         },</span>
<span class="token comment">//         arguments: [</span>
<span class="token comment">//           {</span>
<span class="token comment">//             type: 'NumberLiteral',</span>
<span class="token comment">//             value: '2',</span>
<span class="token comment">//           },</span>
<span class="token comment">//           {</span>
<span class="token comment">//             type: 'CallExpression',</span>
<span class="token comment">//             callee: {</span>
<span class="token comment">//               type: 'Identifier',</span>
<span class="token comment">//               name: 'subtract',</span>
<span class="token comment">//             },</span>
<span class="token comment">//             arguments: [</span>
<span class="token comment">//               {</span>
<span class="token comment">//                 type: 'NumberLiteral',</span>
<span class="token comment">//                 value: '4',</span>
<span class="token comment">//               },</span>
<span class="token comment">//               {</span>
<span class="token comment">//                 type: 'NumberLiteral',</span>
<span class="token comment">//                 value: '2',</span>
<span class="token comment">//               },</span>
<span class="token comment">//             ],</span>
<span class="token comment">//           },</span>
<span class="token comment">//         ],</span>
<span class="token comment">//       },</span>
<span class="token comment">//     },</span>
<span class="token comment">//   ],</span>
<span class="token comment">// }</span>
<span class="token comment">// 代码转换 -&gt; 目标 AST (访问者模式)</span>
<span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function-variable function">tranverser</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">ast<span class="token punctuation">,</span> visitor</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> <span class="token function-variable function">tranverseAarray</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">array<span class="token punctuation">,</span> parent</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    array<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">child</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      <span class="token function">tranverseNode</span><span class="token punctuation">(</span>child<span class="token punctuation">,</span> parent<span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  <span class="token keyword">const</span> <span class="token function-variable function">tranverseNode</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">node<span class="token punctuation">,</span> parent</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">let</span> methods <span class="token operator">=</span> visitor<span class="token punctuation">[</span>node<span class="token punctuation">.</span>type<span class="token punctuation">]</span>

    <span class="token comment">// 执行访问者 visitor 上定义的钩子，这样可以抽离处理函数，逻辑更清晰</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>methods <span class="token operator">&amp;&amp;</span> methods<span class="token punctuation">.</span>enter<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      methods<span class="token punctuation">.</span><span class="token function">enter</span><span class="token punctuation">(</span>node<span class="token punctuation">,</span> parent<span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>methods <span class="token operator">&amp;&amp;</span> methods<span class="token punctuation">.</span>exit<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      methods<span class="token punctuation">.</span><span class="token function">exit</span><span class="token punctuation">(</span>node<span class="token punctuation">,</span> parent<span class="token punctuation">)</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">const</span> switchEnum <span class="token operator">=</span> <span class="token punctuation">{</span>
      <span class="token function">Program</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token function">tranverseAarray</span><span class="token punctuation">(</span>node<span class="token punctuation">.</span>body<span class="token punctuation">,</span> node<span class="token punctuation">)</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token function">CallExpression</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token function">tranverseAarray</span><span class="token punctuation">(</span>node<span class="token punctuation">.</span>params<span class="token punctuation">,</span> node<span class="token punctuation">)</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token function">NumberLiteral</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token function">StringLiteral</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">try</span> <span class="token punctuation">{</span>
      switchEnum<span class="token punctuation">[</span>node<span class="token punctuation">.</span>type<span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">TypeError</span><span class="token punctuation">(</span>node<span class="token punctuation">.</span>type<span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>

  <span class="token function">tranverseNode</span><span class="token punctuation">(</span>ast<span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function-variable function">transformer</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">ast</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">let</span> newAst <span class="token operator">=</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'Program'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">body</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span>

  <span class="token comment">// 将 原始ast 的上下文 指向 newAst.body，这样后续操作会将数据直接填入 newAst.body</span>
  ast<span class="token punctuation">.</span>_context <span class="token operator">=</span> newAst<span class="token punctuation">.</span>body

  <span class="token function">tranverser</span><span class="token punctuation">(</span>ast<span class="token punctuation">,</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">NumberLiteral</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token function">enter</span><span class="token punctuation">(</span><span class="token parameter">node<span class="token punctuation">,</span> parent</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token comment">// 第一次执行到此处，parent._context 即 newAst.body，后续就是对应节点的上下文</span>
        parent<span class="token punctuation">.</span>_context<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
          <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'NumberLiteral'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">value</span><span class="token operator">:</span> node<span class="token punctuation">.</span>value<span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token literal-property property">StringLiteral</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token function">enter</span><span class="token punctuation">(</span><span class="token parameter">node<span class="token punctuation">,</span> parent</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        parent<span class="token punctuation">.</span>_context<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
          <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'StringLiteral'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">value</span><span class="token operator">:</span> node<span class="token punctuation">.</span>value<span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token literal-property property">CallExpression</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token function">enter</span><span class="token punctuation">(</span><span class="token parameter">node<span class="token punctuation">,</span> parent</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">let</span> expression <span class="token operator">=</span> <span class="token punctuation">{</span>
          <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'CallExpression'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">callee</span><span class="token operator">:</span> <span class="token punctuation">{</span>
            <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'Identifier'</span><span class="token punctuation">,</span>
            <span class="token literal-property property">name</span><span class="token operator">:</span> node<span class="token punctuation">.</span>name<span class="token punctuation">,</span>
          <span class="token punctuation">}</span><span class="token punctuation">,</span>
          <span class="token literal-property property">arguments</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span>

        <span class="token comment">// 将当前上下文 指向 expression.arguments</span>
        node<span class="token punctuation">.</span>_context <span class="token operator">=</span> expression<span class="token punctuation">.</span>arguments

        <span class="token keyword">if</span> <span class="token punctuation">(</span>parent<span class="token punctuation">.</span>type <span class="token operator">!==</span> <span class="token string">'CallExpression'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
          expression <span class="token operator">=</span> <span class="token punctuation">{</span>
            <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'ExpressionStatement'</span><span class="token punctuation">,</span>
            expression<span class="token punctuation">,</span>
          <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
        <span class="token comment">// 将表达式数据 保存到 父级上下文</span>
        parent<span class="token punctuation">.</span>_context<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>expression<span class="token punctuation">)</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>

  <span class="token keyword">return</span> newAst
<span class="token punctuation">}</span>

<span class="token comment">// 代码生成 -&gt; 新code</span>
<span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function-variable function">codeGenerator</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">node</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> switchEnum <span class="token operator">=</span> <span class="token punctuation">{</span>
    <span class="token function-variable function">Program</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> node<span class="token punctuation">.</span>body<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>codeGenerator<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token function-variable function">ExpressionStatement</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token function">codeGenerator</span><span class="token punctuation">(</span>node<span class="token punctuation">.</span>expression<span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token string">';'</span><span class="token punctuation">,</span>
    <span class="token function-variable function">CallExpression</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> <span class="token function">codeGenerator</span><span class="token punctuation">(</span>node<span class="token punctuation">.</span>callee<span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token string">'('</span> <span class="token operator">+</span> node<span class="token punctuation">.</span>arguments<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>codeGenerator<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">','</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token string">')'</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token function-variable function">Identifier</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> node<span class="token punctuation">.</span>name<span class="token punctuation">,</span>
    <span class="token function-variable function">NumberLiteral</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> node<span class="token punctuation">.</span>value<span class="token punctuation">,</span>
    <span class="token function-variable function">StringLiteral</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token string">'&quot;'</span> <span class="token operator">+</span> node<span class="token punctuation">.</span>value <span class="token operator">+</span> <span class="token string">'&quot;'</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span>

  <span class="token keyword">try</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> switchEnum<span class="token punctuation">[</span>node<span class="token punctuation">.</span>type<span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">TypeError</span><span class="token punctuation">(</span>node<span class="token punctuation">.</span>type<span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><div class="right-pendant"><a href="dingtalk://dingtalkclient/action/sendmsg?dingtalk_id=zpizb5p" class="pendant__icon"><img title="点击跳转钉钉联系我" src="/blog/assets/img/dingdinglogo.png" alt="点击跳转钉钉联系我"></a><a href="javascript:;" class="pendant__icon"><div class="img-container"><div><!----> <img src="/blog/assets/img/myqq.jpg" class="cover-img"></div></div></a><a href="javascript:;" class="pendant__icon"><div class="img-container"><div><!----> <img src="/blog/assets/img/mywx.jpg" class="cover-img"></div></div></a></div></div> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">更新时间:</span> <span class="time">2023年9月4日星期一上午10点30分</span></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
      ←
      <a href="/blog/article/前端工程化/CI&amp;CD/CI&amp;CD.html" class="prev">
        持续集成与交付
      </a></span> <span class="next"><a href="/blog/article/前端工程化/CI&amp;CD/编译打包/webpack/webpack之loader.html">
        webpack
      </a>
      →
    </span></p></div> </main></div><div class="global-ui"></div></div>
    <script src="/blog/assets/js/app.7b4540b9.js" defer></script><script src="/blog/assets/js/2.b0da3abb.js" defer></script><script src="/blog/assets/js/60.73f12c35.js" defer></script><script src="/blog/assets/js/3.d02dbad1.js" defer></script><script src="/blog/assets/js/11.d9c57454.js" defer></script><script src="/blog/assets/js/6.e0517a23.js" defer></script><script src="/blog/assets/js/4.e142f4c4.js" defer></script>
  </body>
</html>
